-- 4位序列检测器，匹配则led灯亮


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity sequence is
    port(
        clk, clear : in std_logic;
        d : in std_logic;   -- 1位1位的输入
        presets : in std_logic_vector(3 downto 0);
        led : out std_logic
    );
end sequence;

-- 方法1
architecture behave of sequence is    
    type state_type is (s0, s1, s2, s3);    -- 4位分别匹配到状态
    signal state : state_type;
begin

    process(clk, clear) begin
        if clear = '1' then
            state <= s0; led <= 0;
        elsif clk'event and clk = '1' then        
            case state is 
            when s0 => if d = presets(3) then
                            state <= s1; led <= 0;  -- 3
                        else
                            state <= s0; led <= 0;
                        end if;
            when s1 => if d = presets(2) then
                            state <= s2; led <= 0;  -- 2
                        elsif d = presets(3) then
                            state <= s1; led <= 0;
                        else
                            state <= s0; led <= 0;
                        end if;
            when s2 => if d = presets(1) then
                            state <= s3; led <= 0;  -- 1
                        elsif d = presets(3) then
                            state <= s1; led <= 0;
                        else
                            state <= s0; led <= 0;
                        end if;       
            when s3 => if d = presets(2) then
                            state <= s0; led <= 1;  -- 0
                        elsif d = presets(3) then
                            state <= s1; led <= 0;
                        else
                            state <= s0; led <= 0;
                        end if;   
            end case;
        end if;
    end process;

end behave;


-- 方法2(自己写的！)
architecture behave of sequence is

begin

    process(clk, rst)
        variable index : integer := 0;
    begin
        if rst = '1' then
            index := 0;
        elsif rising_edge(clk) then
            if presets(3 - index) = d then
                index := index + 1;
                led <= '0';
            elsif presets(3) = d then
                    index := 1;   -- 这个数等于第一个数，就设置inddex为1
                    led <= '0';                  
            else
                index := 0;
                led <= '0';                
            end if;
            
            if index > 3 then
                index := 0;
                led <= '1';
            end if;
        end if;
    end process;

end behave;

